es7 https://github.com/rccoder/blog/issues/23
装饰器的原理
语法糖,实则调用 Object.defineProperty,可以添加、修改对象属性
JS 装饰器
Decorator 其实是语法糖,实则调用 Object.defineProperty,可以添加、修改对象属性。Decorator 是 ES7 的一个新语法,目前仍处于第 2 阶段提案中,正如其“装饰器”的叫法所表达的,他通过添加@方法名可以对一些对象进行装饰包装然后返回一个被包装过的对象,可以装饰的对象包括:类,属性,方法等。
在使用它之前需要引入 babel 模块
transform-decorators-legacy编译成 ES5 或 ES6。
1. 类的装饰
当装饰的对象是类时,我们操作的就是这个类本身,即装饰器函数的第一个参数,就是所要装饰的目标类。
@decorator
class A {}
// 等同于
class A {}
A = decorator(A) || A;
123456;
示例:添加一个日志装饰器
@log
class MyClass {}
function log(target) {
// 这个 target 在这里就是 MyClass 这个类
target.prototype.logger = () => `${target.name} 被调用`;
}
const test = new MyClass();
test.logger(); // MyClass 被调用
由于装饰器是表达式,我们也可以在装饰器后面再添加个参数:
@log("hi")
class MyClass {}
function log(text) {
return function (target) {
target.prototype.logger = () => `${text},${target.name} 被调用`;
};
}
const test = new MyClass();
test.logger(); // hello,MyClass 被调用
1234567891011;
2. 属性或方法的装饰
对于类属性或方法的装饰本质是操作其描述符,可以把此时的装饰器理解成是 Object.defineProperty(obj, prop, descriptor)的语法糖。
class C {
@readonly(false)
method() {
console.log("cat");
}
}
function readonly(value) {
return function (target, key, descriptor) {
/**
* 此处 target 为 C.prototype;
* key 为 method;
* 原 descriptor 为:{ value: f, enumarable: false, writable: true, configurable: true }
*/
descriptor.writable = value;
return descriptor;
};
}
const c = new C();
c.method = () => console.log("dog");
c.method(); // cat
请介绍一下装饰者模式,并实现
装饰器(Decorator)用来增强 JavaScript 类(class)的功能,许多面向对象的语言都有这种语法,如 Java 的注解(Annotation)。
饰器是一种函数,写成@ + 函数名,可以用来装饰四种类型的值。
- 类。 操作类本身。
- 类的属性。 通过 Object.defineProperty() 操作类的属性。
- 类的方法
- 存值器(setter)和取值器(getter)
class C {
@trace
toString() {
return "C";
}
}
// 相当于
C.prototype.toString = trace(C.prototype.toString);
装饰器
是如何实现的?
https://segmentfault.com/p/1210000009968000/read
为什么装饰器不能用于函数
装饰器只能用于类和类的方法,不能用于函数,因为存在函数提升。
总之,由于存在函数提升,使得装饰器不能用于函数。类是不会提升的,所以就没有这方面的问题。
另一方面,如果一定要装饰函数,可以采用高阶函数的形式直接执行。